package com.zjh.workflow.flowable.service.impl;


import com.zjh.admin.entity.DAO.SysUserEntity;
import com.zjh.admin.entity.VO.SysUserVO;
import com.zjh.admin.service.UserService;
import com.zjh.common.entity.LoginUser;
import com.zjh.common.entity.Response;
import com.zjh.common.entity.ResponseCode;
import com.zjh.common.exception.ServiceException;
import com.zjh.common.utils.RequestContext;
import com.zjh.workflow.flowable.constant.FlowConstant;
import com.zjh.workflow.flowable.entity.TaskInputParam;
import com.zjh.workflow.flowable.entity.enums.CommentTypeEnum;
import com.zjh.workflow.flowable.entity.wrapper.FlowTaskDto;
import com.zjh.workflow.flowable.service.IFlowableBpmnModelService;
import com.zjh.workflow.flowable.service.TaskHandleService;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.EndEvent;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;


@Service
public class TaskHandleServiceImpl implements TaskHandleService {

    @Resource
    protected ManagementService managementService;
    @Resource
    private RepositoryService repositoryService;
    @Resource
    private HistoryService historyService;
    @Resource
    private RuntimeService runtimeService;

    @Resource
    private TaskService taskService;
    @Resource
    private UserService userService;
    @Resource
    private BaseProcessService baseProcessService;
    @Resource
    private IFlowableBpmnModelService flowableBpmnModelService;


    @Override
    public List<FlowTaskDto> getTodoList(SysUserVO sysUserVO) {

        List<FlowTaskDto> res = new ArrayList<>();

        TaskQuery taskQuery = taskService.createTaskQuery()
                .active()
                .includeProcessVariables()
                .taskAssignee(String.valueOf(sysUserVO.getUserId()))
                .orderByTaskCreateTime().desc();

        // 查询的其实就是 act_ru_task 中的记录
        List<Task> tasks = taskQuery.list();// 返回多条记录

        tasks.forEach(task -> {

            FlowTaskDto flowTask = new FlowTaskDto();

            // 当前流程信息
            flowTask.setTaskId(task.getId());
            flowTask.setTaskDefKey(task.getTaskDefinitionKey());
            flowTask.setCreateTime(task.getCreateTime());
            flowTask.setProcDefId(task.getProcessDefinitionId());
            flowTask.setTaskName(task.getName());

            // 流程定义信息
            ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(task.getProcessDefinitionId())
                    .singleResult();
            flowTask.setDeployId(pd.getDeploymentId());
            flowTask.setProcDefName(pd.getName());
            flowTask.setProcDefVersion(pd.getVersion());
            flowTask.setProcInsId(task.getProcessInstanceId());


            // 流程发起人信息
            HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(task.getProcessInstanceId())
                    .singleResult();
            flowTask.setBusinessKey(historicProcessInstance.getBusinessKey());

            // 获取发起人信息
            SysUserEntity startUser = userService.getUserById(Long.valueOf(historicProcessInstance.getStartUserId()));
            flowTask.setStartUserId(startUser.getUsername());
            flowTask.setStartUserName(startUser.getNickname());


            res.add(flowTask);

        });

        return res;
    }

    @Override
    public void approveTask(TaskInputParam params) {

        LoginUser loginUser = RequestContext.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前登陆用户为空");
        }

        String processInstanceId = params.getInstanceId();
        String taskId = params.getTaskId();
        if (StringUtils.isBlank(processInstanceId) || StringUtils.isBlank(taskId)) {
            throw new ServiceException("缺少必要参数processInstanceId and taskId");
        }

        //1.查看当前任务是存在
        TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();
        if (taskEntity == null) {
            throw new ServiceException("没有此任务，请确认!");
        }

        //2.委派处理
        if (DelegationState.PENDING.equals(taskEntity.getDelegationState())) {
            //2.1生成历史记录
            TaskEntity task = baseProcessService.createSubTask(taskEntity, String.valueOf(loginUser.getUserId()));
            taskService.complete(task.getId());
            taskId = task.getId();
            //2.2执行委派
            taskService.resolveTask(taskId, params.getVariables());
        } else {
            //3.1修改执行人 其实我这里就相当于签收了
            taskService.setAssignee(taskId, String.valueOf(loginUser.getUserId()));
            //3.2执行任务
            taskService.complete(taskId, params.getVariables());
            //4.处理加签父任务
            String parentTaskId = taskEntity.getParentTaskId();
            if (StringUtils.isNotBlank(parentTaskId)) {
                String tableName = managementService.getTableName(TaskEntity.class);
                String sql = "select count(1) from " + tableName + " where PARENT_TASK_ID_=#{parentTaskId}";
                long subTaskCount = taskService.createNativeTaskQuery().sql(sql).parameter("parentTaskId", parentTaskId).count();
                if (subTaskCount == 0) {
                    Task task = taskService.createTaskQuery().taskId(parentTaskId).singleResult();
                    //处理前后加签的任务
                    taskService.resolveTask(parentTaskId);
                    if (FlowConstant.AFTER_ADDSIGN.equals(task.getScopeType())) {
                        taskService.complete(parentTaskId);
                    }
                }
            }
        }

        //5.生成审批意见
        baseProcessService.addComment(taskId, String.valueOf(loginUser.getUserId()), processInstanceId,
                CommentTypeEnum.SP.toString(), params.getComment());

    }

    @Override
    public Response<String> backToStepTask(TaskInputParam taskInputParam) {
        Response res = new Response();

        LoginUser loginUser = RequestContext.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前登陆用户为空");
        }

        String taskId = taskInputParam.getTaskId();
        if (StringUtils.isBlank(taskId)) {
            throw new ServiceException("taskId 不能为空");
        }

        String processInstanceId = taskInputParam.getInstanceId();
        if (StringUtils.isBlank(processInstanceId)) {
            throw new ServiceException("ProcessInstanceId 不能为空");
        }

        String comment = taskInputParam.getComment(); // 审批意见
        if (StringUtils.isBlank(comment)) {
            throw new ServiceException("驳回意见不能为空");
        }

        String distFlowElementId = taskInputParam.getDestNodeId(); // 目标节点
        if (StringUtils.isBlank(distFlowElementId)) {
            throw new ServiceException("驳回目标节点不能为空");
        }

        TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();
        //1.把当前的节点设置为空
        if (taskEntity != null) {
            //2.设置审批人
            taskEntity.setAssignee(String.valueOf(loginUser.getUserId()));
            taskService.saveTask(taskEntity);

            //3.添加驳回意见
            baseProcessService.addComment(taskId, String.valueOf(loginUser.getUserId()), processInstanceId,
                    CommentTypeEnum.BH.toString(), comment);

            //4.处理提交人节点
            FlowNode distActivity = flowableBpmnModelService.findFlowNodeByActivityId(taskEntity.getProcessDefinitionId(), distFlowElementId);
            if (distActivity != null) {
                if (FlowConstant.FLOW_SUBMITTER.equals(distActivity.getName())) {
                    ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(taskEntity.getProcessInstanceId()).singleResult();
                    runtimeService.setVariable(processInstanceId, FlowConstant.FLOW_SUBMITTER_VAR, processInstance.getStartUserId());
                }
            }

            //5.删除节点
            baseProcessService.deleteActivity(distFlowElementId, taskEntity.getProcessInstanceId());
            List<String> executionIds = new ArrayList<>();

            //6.判断节点是不是子流程内部的节点
            if (flowableBpmnModelService.checkActivitySubprocessByActivityId(taskEntity.getProcessDefinitionId(),
                    distFlowElementId)
                    && flowableBpmnModelService.checkActivitySubprocessByActivityId(taskEntity.getProcessDefinitionId(),
                    taskEntity.getTaskDefinitionKey())) {
                //6.1 子流程内部驳回
                Execution executionTask = runtimeService.createExecutionQuery().executionId(taskEntity.getExecutionId()).singleResult();
                String parentId = executionTask.getParentId();
                List<Execution> executions = runtimeService.createExecutionQuery().parentId(parentId).list();
                executions.forEach(execution -> executionIds.add(execution.getId()));
                baseProcessService.moveExecutionsToSingleActivityId(executionIds, distFlowElementId);
            } else {
                //6.2 普通驳回
                List<Execution> executions = runtimeService.createExecutionQuery().parentId(taskEntity.getProcessInstanceId()).list();
                executions.forEach(execution -> executionIds.add(execution.getId()));
                baseProcessService.moveExecutionsToSingleActivityId(executionIds, distFlowElementId);
            }

            res.setCode(ResponseCode.SUCCESS.getCode());
            res.setData("驳回成功");
        } else {
            res.setCode(ResponseCode.FAILED.getCode());
            res.setData("不存在任务实例,请确认!");
        }

        return res;
    }

    @Override
    public Response<String> stopProcessInstanceById(TaskInputParam taskInputParam) {
        Response<String> res = null;

        LoginUser loginUser = RequestContext.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前登陆用户为空");
        }

        String processInstanceId = taskInputParam.getInstanceId();
        String comment = taskInputParam.getComment();

        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(processInstanceId).singleResult();

        if (processInstance != null) {
            //1、添加审批记录
            baseProcessService.addComment(String.valueOf(loginUser.getUserId()), processInstanceId, CommentTypeEnum.LCZZ.toString(),
                    comment);
            List<EndEvent> endNodes = flowableBpmnModelService.findEndFlowElement(processInstance.getProcessDefinitionId());
            String endId = endNodes.get(0).getId();
            //2、执行终止
            List<Execution> executions = runtimeService.createExecutionQuery().parentId(processInstanceId).list();
            List<String> executionIds = new ArrayList<>();
            executions.forEach(execution -> executionIds.add(execution.getId()));
            baseProcessService.moveExecutionsToSingleActivityId(executionIds, endId);
            res = Response.success();
        } else {
            res = Response.error("不存在运行的流程实例,请确认!");
        }
        return res;
    }

}
